//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  http://www.nopCommerce.com/License.aspx. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations under the License.
// 
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
// 
// Contributor(s): _______. 
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using Tathata.Common.Caching;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data.Common;
using System.Data;
using System.Globalization;
using Tathata.Common.DAL;
using Tathata.Common.BLL.Entities;
using Tathata.Common.BLL.EntityCollections;
using Tathata.Common.DAL.Managers;
using System.Net.Mail;
using Tathata.Common.BLL.Enums;
using Tathata.Common.Utils;
using System.Net;
using System.Collections.Specialized;
using System.Web;

namespace Tathata.Common.BLL.Managers
{
    /// <summary>
    /// Message manager
    /// </summary>
    public class MessageManager
    {
        #region Methods
        /// <summary>
        /// Sends a welcome message to a customer
        /// </summary>
        /// <param name="customer">Customer instance</param>
        /// <returns>True if the message is successfully sent; otherwise, false.</returns>
        public static bool SendCustomerWelcomeMessage(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            string TemplateName = "Customer.WelcomeMessage";
            MessageTemplate messageTemplate = MessageTemplateManager.GetByMessageTemplateName(TemplateName);
            if (messageTemplate == null)
                throw new Exception(string.Format("Message template ({0}) couldn't be loaded", TemplateName));

            try
            {
                string subject = ReplaceMessageTemplateTokens(customer, messageTemplate.Subject);
                string body = ReplaceMessageTemplateTokens(customer, messageTemplate.Body);
                List<string> to = new List<string>();
                to.Add(customer.Email);
                SendEmail(subject, body, AdminEmailAddress, to);
            }
            catch (Exception exc)
            {
                LogManager.InsertLog(LogTypeEnum.MailError, string.Format("Error customer welcome message. CustomerID={0}", customer.CustomerID), exc.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// Sends an email validation message to a customer
        /// </summary>
        /// <param name="customer">Customer instance</param>
        /// <returns>True if the message is successfully sent; otherwise, false.</returns>
        public static bool SendCustomerEmailValidationMessage(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            string TemplateName = "Customer.EmailValidationMessage";
            MessageTemplate messageTemplate = MessageTemplateManager.GetByMessageTemplateName(TemplateName);
            if (messageTemplate == null)
                throw new Exception(string.Format("Message template ({0}) couldn't be loaded", TemplateName));

            try
            {
                string subject = ReplaceMessageTemplateTokens(customer, messageTemplate.Subject);
                string body = ReplaceMessageTemplateTokens(customer, messageTemplate.Body);
                List<string> to = new List<string>();
                to.Add(customer.Email);
                SendEmail(subject, body, AdminEmailAddress, to);
            }
            catch (Exception exc)
            {
                LogManager.InsertLog(LogTypeEnum.MailError, "Error sending customer email validation message.", exc.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// Sends password recovery message to a customer
        /// </summary>
        /// <param name="customer">Customer instance</param>
        /// <returns>True if the message is successfully sent; otherwise, false.</returns>
        public static bool SendCustomerPasswordRecoveryMessage(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            string TemplateName = "Customer.PasswordRecovery";
            MessageTemplate messageTemplate = MessageTemplateManager.GetByMessageTemplateName(TemplateName);
            if (messageTemplate == null)
                throw new Exception(string.Format("Message template ({0}) couldn't be loaded", TemplateName));

            try
            {
                string subject = ReplaceMessageTemplateTokens(customer, messageTemplate.Subject);
                string body = ReplaceMessageTemplateTokens(customer, messageTemplate.Body);
                List<string> to = new List<string>();
                to.Add(customer.Email);
                SendEmail(subject, body, AdminEmailAddress, to);
            }
            catch (Exception exc)
            {
                LogManager.InsertLog(LogTypeEnum.MailError, "Error sending customer password recovery message.", exc.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// Sends "email a friend" message
        /// </summary>
        /// <param name="customer">Customer instance</param>
        /// <param name="product">Product instance</param>
        /// <param name="FriendsEmail">Friend's email</param>
        /// <param name="PersonalMessage">Personal message</param>
        /// <returns>True if the message is successfully sent; otherwise, false.</returns>
        public static bool SendEmailAFriendMessage(Customer customer,Product product, string FriendsEmail, string PersonalMessage)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");
            if (product == null)
                throw new ArgumentNullException("product");

            string TemplateName = "Service.EmailAFriend";
            MessageTemplate messageTemplate = MessageTemplateManager.GetByMessageTemplateName(TemplateName);
            if (messageTemplate == null)
                throw new Exception(string.Format("Message template ({0}) couldn't be loaded", TemplateName));

            try
            {
                NameValueCollection additinalKeys = new NameValueCollection();
                additinalKeys.Add("EmailAFriend.PersonalMessage", PersonalMessage);
                string subject = ReplaceMessageTemplateTokens(customer, product, messageTemplate.Subject, additinalKeys);
                string body = ReplaceMessageTemplateTokens(customer, product, messageTemplate.Body, additinalKeys);
                List<string> to = new List<string>();
                to.Add(FriendsEmail);
                SendEmail(subject, body, AdminEmailAddress , to);
            }
            catch (Exception exc)
            {
                LogManager.InsertLog(LogTypeEnum.MailError, "Error sending customer password recovery message.", exc.ToString());
                return false;
            }
            return true;
        }


        /// <summary>
        /// Replaces a message template tokens
        /// </summary>
        /// <param name="customer">Customer instance</param>
        /// <param name="Template">Template</param>
        /// <returns>New template</returns>
        public static string ReplaceMessageTemplateTokens(Customer customer, string Template)
        {
            NameValueCollection tokens = new NameValueCollection();
            tokens.Add("Store.Name", SettingManager.GetSettingValue("Common.StoreName"));
            tokens.Add("Store.URL", SettingManager.GetSettingValue("Common.StoreURL"));
            tokens.Add("Store.Email", AdminEmailAddress);


            tokens.Add("Customer.Email", customer.Email);
            CustomerAttributeCollection customerAttributes = customer.CustomerAttributes;
            CustomerAttribute passwordRecoveryAttr = customerAttributes.FindAttribute("PasswordRecoveryToken", customer.CustomerID);
            if (passwordRecoveryAttr != null)
                tokens.Add("Customer.PasswordRecoveryToken", passwordRecoveryAttr.Value);

            foreach (string token in tokens.Keys)
                Template = Template.Replace(string.Format(@"%{0}%", token), tokens[token]);

            return Template;
        }

        /// <summary>
        /// Replaces a message template tokens
        /// </summary>
        /// <param name="customer">Customer instance</param>
        /// <param name="product">Product instance</param>
        /// <param name="Template">Template</param>
        /// <param name="AdditinalKeys">Additinal keys</param>
        /// <returns>New template</returns>
        public static string ReplaceMessageTemplateTokens(Customer customer, Product product, string Template, NameValueCollection AdditinalKeys)
        {
            NameValueCollection tokens = new NameValueCollection();
            tokens.Add("Store.Name", SettingManager.GetSettingValue("Common.StoreName"));
            tokens.Add("Store.URL", SettingManager.GetSettingValue("Common.StoreURL"));
            tokens.Add("Store.Email", AdminEmailAddress);

            tokens.Add("Customer.Email", customer.Email);
            tokens.Add("Customer.FullName", customer.FullName);

            tokens.Add("Product.Name", product.Name);
            tokens.Add("Product.ShortDescription", product.ShortDescription);
            tokens.Add("Product.ProductURLForCustomer", SEOHelper.GetProductURL(product.ProductID));

            foreach (string token in tokens.Keys)
                Template = Template.Replace(string.Format(@"%{0}%", token), tokens[token]);

            foreach (string token in AdditinalKeys.Keys)
                Template = Template.Replace(string.Format(@"%{0}%", token), AdditinalKeys[token]);

            return Template;
        }

        /// <summary>
        /// Sends an email
        /// </summary>
        /// <param name="Subject">Subject</param>
        /// <param name="Body">Body</param>
        /// <param name="From">From</param>
        /// <param name="To">To</param>
        public static void SendEmail(string Subject, string Body, string From, ICollection<string> To)
        {
            SendEmail(Subject, Body, From, To, new List<string>());
        }

        /// <summary>
        /// Sends an email
        /// </summary>
        /// <param name="Subject">Subject</param>
        /// <param name="Body">Body</param>
        /// <param name="From">From</param>
        /// <param name="To">To</param>
        /// <param name="bcc">Bcc</param>
        public static void SendEmail(string Subject, string Body, string From, ICollection<string> To, ICollection<string> bcc)
        {
            MailMessage message = new MailMessage();
            message.From = new MailAddress(From);
            foreach (string address in To)
                message.To.Add(address);
            if (null != bcc)
                foreach (string address in bcc)
                {
                    message.Bcc.Add(address);
                }

            message.Subject = Subject;
            message.Body = Body;
            message.IsBodyHtml = true;

            SmtpClient smtpClient = new SmtpClient();
            smtpClient.UseDefaultCredentials = AdminEmailUseDefaultCredentials;
            smtpClient.Host = AdminEmailHost;
            smtpClient.Port = AdminEmailPort;
            smtpClient.EnableSsl = AdminEmailEnableSsl;
            if (AdminEmailUseDefaultCredentials)
                smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials;
            else
                smtpClient.Credentials = new NetworkCredential(AdminEmailUser, AdminEmailPassword);
            smtpClient.Send(message);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets an admin email address
        /// </summary>
        public static string AdminEmailAddress
        {
            get
            {
                return SettingManager.GetSettingValue("Email.AdminEmailAddress");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailAddress", value.Trim(), string.Empty);
            }
        }

        /// <summary>
        /// Gets or sets an admin email host
        /// </summary>
        public static string AdminEmailHost
        {
            get
            {
                return SettingManager.GetSettingValue("Email.AdminEmailHost");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailHost", value.Trim(), string.Empty);
            }
        }
        
        /// <summary>
        /// Gets or sets an admin email port
        /// </summary>
        public static int AdminEmailPort
        {
            get
            {
                return SettingManager.GetSettingValueInteger("Email.AdminEmailPort");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailPort", value.ToString(), string.Empty);
            }
        }
        
        /// <summary>
        /// Gets or sets an admin email user name
        /// </summary>
        public static string AdminEmailUser
        {
            get
            {
                return SettingManager.GetSettingValue("Email.AdminEmailUser");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailUser", value.Trim(), string.Empty);
            }
        }
        
        /// <summary>
        /// Gets or sets an admin email password
        /// </summary>
        public static string AdminEmailPassword
        {
            get
            {
                return SettingManager.GetSettingValue("Email.AdminEmailPassword");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailPassword", value, string.Empty);
            }
        }

        /// <summary>
        /// Gets or sets a value that controls whether the default system credentials of the application are sent with requests.
        /// </summary>
        public static bool AdminEmailUseDefaultCredentials
        {
            get
            {
                return SettingManager.GetSettingValueBoolean("Email.AdminEmailUseDefaultCredentials");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailUseDefaultCredentials", value.ToString(), string.Empty);
            }
        }

        /// <summary>
        /// Gets or sets a value that controls whether the SmtpClient uses Secure Sockets Layer (SSL) to encrypt the connection
        /// </summary>
        public static bool AdminEmailEnableSsl
        {
            get
            {
                return SettingManager.GetSettingValueBoolean("Email.AdminEmailEnableSsl");
            }
            set
            {
                SettingManager.SetParam("Email.AdminEmailEnableSsl", value.ToString(), string.Empty);
            }
        }
        #endregion
    }
}
